{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "pn.extension('vtk')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "The ``VTK`` pane renders vtk.js files inside a panel, making it possible to load and interact with complex geometries in 3D.\n",
    "\n",
    "#### Parameters:\n",
    "\n",
    "For details on other options for customizing the component see the [layout](../../how_to/layout/index.md) and [styling](../../how_to/styling/index.md) how-to guides.\n",
    "\n",
    "* **``axes``** (dict): A dictionary with the parameters of the axes to construct in the 3D view.\n",
    "    Must contain at least ``xticker``, ``yticker`` and ``zticker``.\n",
    "    - ``[x|y|z]ticker`` is a dictionary which contains:\n",
    "        - ``ticks`` (array of numbers) - required. Positions in the scene coordinates\n",
    "        of the corresponding axis ticks\n",
    "        - ``labels`` (array of strings) - optional. Label displayed respectively to\n",
    "        the `ticks` positions.\n",
    "\n",
    "        If `labels` are not defined they are inferred from the `ticks` array.\n",
    "    - ``digits``: number of decimal digits when `ticks` are converted to `labels`.\n",
    "    - ``fontsize``: size in pts of the ticks labels.\n",
    "    - ``show_grid``: boolean. If true (default) the axes grid is visible.\n",
    "    - ``grid_opacity``: float between 0-1. Defines the grid opacity.\n",
    "    - ``axes_opacity``: float between 0-1. Defines the axes lines opacity.\n",
    "* **``camera``** (dict): A dictionary reflecting the current state of the VTK camera\n",
    "* **``enable_keybindings``** (bool): A boolean to activate/deactivate keybindings. Bound keys are:\n",
    "  - s: set representation of all actors to *surface*\n",
    "  - w: set representation of all actors to *wireframe*\n",
    "  - v: set representation of all actors to *vertex*\n",
    "  - r: center the actors and move the camera so that all actors are visible\n",
    "  \n",
    "  The mouse must be over the pane to work.\n",
    "  <br>**Warning**: These keybindings may not work as expected in a notebook context, if they interact with already bound keys.\n",
    "* **``orientation_widget``** (bool): A boolean to activate/deactivate the orientation widget in the 3D pane.\n",
    "* **``interactive_orientation_widget``** (bool): If True the orientation widget is clickable and allows to rotate the scene in one of the orthographic projections.\n",
    "* **``object``** (str or object): Can be a string pointing to a local or remote file with a `.vtkjs` extension.\n",
    "___"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The simplest way to construct a ``VTK`` pane is to give it a vtk.js file which it will serialize and embed in the plot. The ``VTK`` pane also supports the regular sizing options provided by Bokeh, including responsive sizing modes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "vtk_pane = pn.pane.VTK(\n",
    "    'https://raw.githubusercontent.com/Kitware/vtk-js/master/Data/StanfordDragon.vtkjs',\n",
    "    sizing_mode='stretch_width', height=400, enable_keybindings=True, orientation_widget=True\n",
    ")\n",
    "\n",
    "vtk_pane"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``VTK`` pane can also be updated like all other pane objects by replacing the ``object``:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "vtk_pane.object = \"https://raw.githubusercontent.com/Kitware/vtk-js-datasets/master/data/vtkjs/TBarAssembly.vtkjs\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Camera control\n",
    "\n",
    "Once a VTK pane has been displayed it will automatically sync the camera state with the Pane object.\n",
    "The camera parameter is updated only at the end of the interaction.\n",
    "We can read the camera state on the corresponding parameter:\n",
    "\n",
    "```python\n",
    "> vtk_pane.camera\n",
    "\n",
    "{'position': [-21.490090356222225, 14.44963146483641, 26.581314468858984],\n",
    " 'focalPoint': [0, 4.969950199127197, 0],\n",
    " 'viewUp': [0.17670012087160802, 0.9635684210080306, -0.20078088883170594],\n",
    " 'directionOfProjection': [0.605834463228546,\n",
    "  -0.2672449261957517,\n",
    "  -0.749362897791989],\n",
    " 'parallelProjection': False,\n",
    " 'useHorizontalViewAngle': False,\n",
    " 'viewAngle': 30,\n",
    " 'parallelScale': 9.180799381276024,\n",
    " 'clippingRange': [26.442079567041056, 44.714416678555395],\n",
    " 'thickness': 1000,\n",
    " 'windowCenter': [0, 0],\n",
    " 'useOffAxisProjection': False,\n",
    " 'screenBottomLeft': [-0.5, -0.5, -0.5],\n",
    " 'screenBottomRight': [0.5, -0.5, -0.5],\n",
    " 'screenTopRight': [0.5, 0.5, -0.5],\n",
    " 'freezeFocalPoint': False,\n",
    " 'useScissor': False,\n",
    " 'projectionMatrix': None,\n",
    " 'viewMatrix': None,\n",
    " 'physicalTranslation': [0, -4.969950199127197, 0],\n",
    " 'physicalScale': 9.180799381276024,\n",
    " 'physicalViewUp': [0, 1, 0],\n",
    " 'physicalViewNorth': [0, 0, -1],\n",
    " 'mtime': 2237,\n",
    " 'distance': 35.47188491341284}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This technique also makes it possible to link the camera of two or more VTK panes together:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "dragon1 = pn.pane.VTK('https://raw.githubusercontent.com/Kitware/vtk-js/master/Data/StanfordDragon.vtkjs',\n",
    "                      height=400, sizing_mode='stretch_width')\n",
    "dragon2 = pn.pane.VTK('https://raw.githubusercontent.com/Kitware/vtk-js/master/Data/StanfordDragon.vtkjs',\n",
    "                      height=400, sizing_mode='stretch_width')\n",
    "\n",
    "dragon1.jslink(dragon2, camera='camera', bidirectional=True)\n",
    "\n",
    "pn.Row(dragon1, dragon2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "and to modify the camera state in Python and trigger an update:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if dragon1.camera:\n",
    "    dragon1.camera['viewAngle'] = 50\n",
    "    dragon1.param.trigger('camera')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Controls\n",
    "\n",
    "The ``VTKJS`` pane exposes a number of options which can be changed from both Python and JavaScript. Try out the effect of these parameters interactively:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pn.Row(vtk_pane.controls(jslink=True), vtk_pane)"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
